package com.org.oracle.factory;

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.ByteArrayOutputStream;
import java.time.Duration;

/**
 * @author: heiye
 * @date: 2024/12/21 下午9:51
 * @version: v1.0.0
 * @description: TODO 有 bug 归还对象没清空数据勿用
 *                    输出文件流工厂 接入了 Apache Commons Pool 2 中对象池管理
 */
@Configuration
public class ByteArrayOutputStreamFactory implements PooledObjectFactory<ByteArrayOutputStream> {

    // 创建 ByteArrayOutputStream 对象池
    @Bean
    public GenericObjectPool<ByteArrayOutputStream> byteArrayOutputStreamPool() {
        // 配置对象池
        GenericObjectPoolConfig<ByteArrayOutputStream> config = new GenericObjectPoolConfig<>();
        // 最大池大小
        config.setMaxTotal(20);
        // 最大空闲对象数
        config.setMaxIdle(10);
        // 最小空闲对象数
        config.setMinIdle(5);
        // 在借用时进行对象验证
        config.setTestOnBorrow(true);
        // 在归还时进行对象验证
        config.setTestOnReturn(true);
        // 设置最大等待时间为 1 秒
        config.setMaxWait(Duration.ofMillis(1000));
        // 禁用 JMX 注册
        config.setJmxEnabled(false);

        // 返回一个对象池实例 使用当前类作为工厂
        return new GenericObjectPool<>(this, config);
    }

    /**
     * 创建一个新的 ByteArrayOutputStream 实例，并将其包装在一个 PooledObject 对象中，方便对象池管理。
     *
     * @return
     * @throws Exception
     */
    @Override
    public PooledObject<ByteArrayOutputStream> makeObject() throws Exception {
        return new DefaultPooledObject<>(new ByteArrayOutputStream());
    }

    /**
     * 当对象从池中被借用并即将使用时调用此方法。它允许我们对池中的对象进行一些初始化操作。
     *
     * @param pooledObject
     * @throws Exception
     */
    @Override
    public void activateObject(PooledObject<ByteArrayOutputStream> pooledObject) throws Exception {
        // 激活时无需处理
    }

    /**
     * 当对象被归还到池中时调用此方法。它允许我们对池中的对象进行一些清理操作，以便对象下次被借用时是干净的。
     *
     * @param pooledObject
     * @throws Exception
     */
    @Override
    public void passivateObject(PooledObject<ByteArrayOutputStream> pooledObject) throws Exception {
        // 归还池时清空流
        pooledObject.getObject().close();
    }

    /**
     * 验证池中的对象是否仍然有效。当对象池回收对象时，它会验证该对象是否仍然适合使用。如果验证失败，池会销毁该对象并重新创建一个新的。
     *
     * @param pooledObject
     * @return
     */
    @Override
    public boolean validateObject(PooledObject<ByteArrayOutputStream> pooledObject) {
        // 认为流对象有效
        return true;
    }

    /**
     * 销毁池中的对象。每当对象池中不再使用某个 ByteArrayOutputStream 对象时，调用此方法。
     *
     * @param pooledObject
     * @throws Exception
     */
    @Override
    public void destroyObject(PooledObject<ByteArrayOutputStream> pooledObject) throws Exception {
        // 清空缓冲区
        pooledObject.getObject().reset();
    }
}
